package br.usp.poli.entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.validator.NotNull;

@SuppressWarnings("serial")
@Entity
public class Experiment implements Serializable {
	@Id
	@GeneratedValue()
	private Long id;
	@Cascade(value=CascadeType.ALL)
	@Fetch(value=FetchMode.JOIN)
	@OneToOne
	@NotNull
	private DataSetMetadata dataSetMetadata = new DataSetMetadata();
	@Column(nullable = false)
	@ManyToMany
	private List<Variable> variables = new ArrayList<Variable>();
	@Cascade(value=CascadeType.ALL)
	@OneToOne
	private DataSet dataSet = new DataSet();
	@Column(nullable = false)
	@Enumerated
	private Status status;
	@OneToMany
	private List<DataTable> dataTables = new ArrayList<DataTable>(); 
	
	public enum Status {

		SUBMITED("submited"), INITIALIZING("initializing"), RUNNING("running"), FINISHED(
				"finished");

		private final String value;

		Status(String v) {
			this.value = v;
		}

		public String value() {
			return value;
		}

		public static Status fromValue(String v) {
			for (Status c : Status.values()) {
				if (c.value.equals(v)) {
					return c;
				}
			}
			throw new IllegalArgumentException(v);
		}
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public DataSetMetadata getDataSetMetadata() {
		return dataSetMetadata;
	}

	public void setDataSetMetadata(DataSetMetadata dataSetMetadata) {
		this.dataSetMetadata = dataSetMetadata;
	}

	public Status getStatus() {
		return status;
	}

	public void setStatus(Status status) {
		this.status = status;
	}

	public List<Variable> getVariables() {
		return variables;
	}

	/**
	 * @param e
	 * @return
	 * @see br.usp.poli.entity.DataSet#add(br.usp.poli.entity.Occurrence)
	 */
	public boolean add(Occurrence e) {
		if (e != null && variables.contains(e)) {
			return dataSet.add(e);
		} else
			throw new IllegalArgumentException("Variable does not exist.");
	}

	/**
	 * @param o
	 * @return
	 * @see br.usp.poli.entity.DataSet#remove(java.lang.Object)
	 */
	public boolean remove(Object o) {
		return dataSet.remove(o);
	}
	
	@Override
	public String toString() {
		return "["+getId()+"] ("+getStatus().value+") "	+ dataSetMetadata.toString();
	}

	public DataSet getDataSet() {
		return dataSet;
	}

	public void setDataSet(DataSet dataSet) {
		this.dataSet = dataSet;
	}

	public List<DataTable> getDataTables() {
		return dataTables;
	}

	public void setDataTables(List<DataTable> dataTables) {
		this.dataTables = dataTables;
	}

	public void setVariables(List<Variable> variables) {
		this.variables = variables;
	}

}
